package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;




/**
 * 自定义切面类
 */
@Aspect
@Component//需要交给spring容器管理
@Slf4j
public class AutoFillAspect {
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")//我感觉这样写，增强范围是一样的，但是扫描的范围变小了
    public void AutoFillPointCut(){}
    @Around("AutoFillPointCut()")//我要用前置通知
    public void autoFill(ProceedingJoinPoint joinPoint) throws Throwable
    { log.info("开始进行公共字段自动填充==>AOP");
        //获取被增强方法上的注解
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();//获得被增强的方法签名(方法的相关信息，并不是本身)表明了返回值,方法名字和形参。强转成子接口。子接口肯定属性更多更实用
        //  methodSignature.getMethod();获取的是方法本身，可以对方法进行操作
        AutoFill annotation = methodSignature.getMethod().getAnnotation(AutoFill.class);//获得方法上面加的注解
        OperationType value = annotation.value();//获得注解里面value的数值
         //获取被增强方法的形参

        Object[] args = joinPoint.getArgs();
      if(args==null)
      {
       return;
      }
      Object entity=args[0];//拿到实体对象

        //准备数值
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

        //为形参的实体对象设置数值
       if(value==OperationType.INSERT)
       {//为四个公共字段赋值
//             entity.getClass().getDeclaredMethod("setCreateTime",LocalDateTime.class).invoke(entity,now);
//             entity.getClass().getDeclaredMethod("setCreateUser",Long.class).invoke(entity,currentId);
//             entity.getClass().getDeclaredMethod("setUpdateUser",Long.class).invoke(entity,currentId);
//             entity.getClass().getDeclaredMethod("setUpdateTime",LocalDateTime.class).invoke(entity,now);
           //用常量代替一下字符串
           entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME,LocalDateTime.class).invoke(entity,now);
           entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER,Long.class).invoke(entity,currentId);
           entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class).invoke(entity,currentId);
           entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,LocalDateTime.class).invoke(entity,now);
       }
       else if(value==OperationType.UPDATE)
       {//为2个公共字段赋值
           entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class).invoke(entity,currentId);
           entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,LocalDateTime.class).invoke(entity,now);
       }
        joinPoint.proceed();
    }
}
